package gin

import (
	authpb "e-commerce/services/auth-service/api/pb"
	"e-commerce/services/payment-service/internal/service"
	"fmt"
	"log"
	"net/http"
	"os"
	"strconv"

	"github.com/gin-gonic/gin"
	"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"gopkg.in/yaml.v3"
)

type AuthClient struct {
	client authpb.AuthServiceClient
	conn   *grpc.ClientConn
}

type PaymentHandler struct {
	PaymentService *service.PaymentService
	AuthClient     *AuthClient
}

type Config struct {
	Auth AuthConfig `yaml:"auth_service"`
}

type AuthConfig struct {
	Addr string `yaml:"addr"`
}

func NewAuthClient(configPath string) (*AuthClient, error) {
	yamlFile, err := os.ReadFile(configPath)
	if err != nil {
		return nil, err
	}
	var config Config
	err = yaml.Unmarshal(yamlFile, &config)
	if err != nil {
		return nil, err
	}
	log.Println("auth service addr: ", config.Auth.Addr)
	conn, err := grpc.NewClient(
		config.Auth.Addr,
		grpc.WithTransportCredentials(insecure.NewCredentials()),
		grpc.WithStatsHandler(otelgrpc.NewClientHandler()),
	)
	if err != nil {
		return nil, err
	}
	return &AuthClient{
		client: authpb.NewAuthServiceClient(conn),
		conn:   conn,
	}, nil
}

func NewPaymentHandler(configPath string) (*PaymentHandler, error) {
	paymentService, err := service.NewPaymentService(configPath)
	if err != nil {
		return nil, fmt.Errorf("failed to create payment service: %v", err)
	}
	authClient, err := NewAuthClient(configPath)
	if err != nil {
		return nil, fmt.Errorf("failed to create auth client: %v", err)
	}
	return &PaymentHandler{
		PaymentService: paymentService,
		AuthClient:     authClient,
	}, nil
}

func (h *PaymentHandler) MarkOrderPaidSuccess(c *gin.Context) {
	orderID := c.Param("orderID")
	orderIDInt64, err := strconv.ParseInt(orderID, 10, 64)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"message": "订单ID格式错误", "error": err.Error()})
		return
	}
	err = h.PaymentService.MarkOrderPaidSuccess(c.Request.Context(), orderIDInt64)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"message": "订单支付标记失败", "error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "订单支付成功"})
}

func (h *PaymentHandler) MarkOrderPaidFailed(c *gin.Context) {
	orderID := c.Param("orderID")
	orderIDInt64, err := strconv.ParseInt(orderID, 10, 64)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"message": "订单ID格式错误", "error": err.Error()})
		return
	}
	err = h.PaymentService.MarkOrderPaidFailed(c.Request.Context(), orderIDInt64)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"message": "订单支付标记失败", "error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "订单支付失败"})
}

func (h *PaymentHandler) Middleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		token := c.GetHeader("Authorization")
		if token == "" {
			c.JSON(http.StatusUnauthorized, gin.H{"error": "Missing authorization token"})
			c.Abort()
			return
		}
		response, err := h.AuthClient.client.ValidateToken(c.Request.Context(), &authpb.ValidateTokenRequest{
			Token: token,
		})
		if err != nil {
			c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
			c.Abort()
			return
		}
		if response.Valid {
			c.Set("user_id", response.UserId)
			c.Set("role", response.Role)
			c.Next()
		} else {
			c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
			c.Abort()
			return
		}
	}
}
